 
  

 






<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do?Id=167 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:28:07 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
<head>
 <title>
  Java Practices -> Input dialogs
 </title>
 <link rel="stylesheet" type="text/css" href="../stylesheet8.css" media="all">
 
 <link rel="shortcut icon" href='../images/favicon.ico' type="image/vnd.microsoft.icon">
 <meta name="description" content="Concise presentations of java programming practices, tasks, and conventions, amply illustrated with syntax highlighted code examples.">
 
 <meta name='keywords' content='regex,RegexInputVerifier,regexp,regular,StandardEditor,StockEditor,validate,validation,dialog,swing,java,java programming,java practices,java idiom,java style,java design patterns,java coding conventions,'>
 
 
</head>
 
<body>


<div class='menu-bar'>
 
  <a href='../home/HomeAction.html' title='Table of Contents'>Home</a> |
  <a href='../vote/VoteSummaryAction-2.html' title='View Poll Results'>Poll</a> |
   
  <A href='../feedback/FeedbackAction451f-2.html?Operation=Show' title='Send Your Feedback'>Wiki</a> |
  <b><a href='../source/SourceAction-2.html' title='Grab Source Code'>Source Code</a></b><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |

  <a href='http://www.web4j.com/Java_Web_Application_Framework_Overview.jsp?From=1' title='Free Download - Java Web Application Framework'><b>WEB4J</b></a> |
  
  <a href='http://www.date4j.net/' title='Replacement for java.util.Date'><b>DATE4J</b></a> |

   <a href='../references/ReferencesAction-2.html' title='References'>Links</a>
   
  <form action='http://www.javapractices.com/search/SearchAction.do' method='get' class='search-form'>
   <input type='text' name='SearchTerms' value="" size=12 maxlength=50 class='search'>
   <input type='submit' value="Search">
  </form>
 
</div>

<P>



  

 






<p class="display-messages">

 

 

</p>


<div class="main-layout">
 
   

 




<div class='page-title'>Input dialogs</div>

<div class='main-body'>
 
<br>Input dialogs allows users to input new items, or to change old ones.
It is often helpful to implement a class which can handle both cases, since
their data validation requirements are often identical.

<p><b>Example</b>

<p>Here, <tt>StockEditor</tt> can either add a new <tt>Stock</tt> object,
or change a <tt>Stock</tt> which already exists. When a change is performed,
all input fields are pre-populated with current values. When an add is
performed, all fields are either blank or pre-populated with default values.
<p>StockEditor uses <tt><a href="TopicActioncded-2.html">RegexInputVerifier</a></tt>
for all text validations, using regular expressions. Text validation proceeds
as follows :
<ul>
<li>
the user enters text into a <tt>JTextField</tt></li>

<li>
when focus leaves the <tt>JTextField</tt>, the input is verified versus
a specified regular expression</li>

<li>
if invalid, the text of the <tt>JTextField</tt> is altered to explicitly
show what is invalid, and the system beeps</li>

<li>
the validation mechanism does not force the focus to remain in the offending
<tt>JTextField</tt></li>
</ul>
For example, here is the result of inputing an invalid <tt>Quantity</tt>,
which must be an integer :
<p><IMG SRC="../images/ChangeStockInvalid.gif" height=196 width=351 ALT="Response to invalid input" border=0>
<p>When the OK button is selected, the input is processed only if
<ul>
<li>
The "INVALID" text is absent from the start of all text fields</li>

<li>
<tt>Stock.isValidInput</tt> returns <tt>true</tt> (this is a second, independent
check)</li>
</ul>
If there is an error, the user is informed by a <tt>JOptionPane</tt> message.
<br>
<PRE>

<span class='keyword'>package</span> hirondelle.stocks.portfolio;

<span class='keyword'>import</span> java.util.*;
<span class='keyword'>import</span> java.util.regex.Pattern;
<span class='keyword'>import</span> java.math.BigDecimal;
<span class='keyword'>import</span> javax.swing.*;
<span class='keyword'>import</span> java.awt.*;
<span class='keyword'>import</span> java.awt.event.*;

<span class='keyword'>import</span> hirondelle.stocks.quotes.Stock;
<span class='keyword'>import</span> hirondelle.stocks.quotes.Exchange;
<span class='keyword'>import</span> hirondelle.stocks.util.Args;
<span class='keyword'>import</span> hirondelle.stocks.util.Util;
<span class='keyword'>import</span> hirondelle.stocks.util.Consts;
<span class='keyword'>import</span> hirondelle.stocks.util.ui.StandardEditor;
<span class='keyword'>import</span> hirondelle.stocks.util.ui.UiUtil;

<span class='comment'>/**
* Dialog allows user to either add new a {@link Stock} to the 
* {@link CurrentPortfolio}, or to change the parameters of a &lt;tt&gt;Stock&lt;/tt&gt;
* which is already in the &lt;tt&gt;CurrentPortfolio&lt;/tt&gt;.
*/</span>
<span class='keyword'>final</span> <span class='keyword'>class</span> StockEditor {
  
  <span class='comment'>/**
  * Constructor.
  *  
  * @param aFrame parent to which dialogs of this class are attached.
  */</span>
  StockEditor(JFrame aFrame) {
    Args.checkForNull(aFrame);
    fFrame = aFrame;
  }
  
  <span class='comment'>/**
  * Return the {@link Stock} representing a new 
  * item which the user has input, or &lt;tt&gt;null&lt;/tt&gt; if the user cancels the dialog.
  */</span>
  Stock addStock(){
    showDialog(<span class='literal'>"Add New Stock"</span>, <span class='keyword'>null</span>);
    <span class='keyword'>return</span> fNewStock;
  }

  <span class='comment'>/**
  * Return the possibly-edited version of &lt;tt&gt;aOldStock&lt;/tt&gt;, representing 
  * the desired changes, or &lt;tt&gt;null&lt;/tt&gt; if the user cancels the dialog.
  * 
  * @param aOldStock {@link Stock} which the end user wishes to change.
  */</span>
  Stock changeStock(Stock aOldStock){
    Args.checkForNull(aOldStock);
    showDialog(<span class='literal'>"Change Stock"</span>, aOldStock);
    <span class='keyword'>return</span> fNewStock;
  }
  
  <span class='comment'>// PRIVATE //
</span>
  <span class='comment'>/**
  * Always returned to the caller, and is null if the user cancels the 
  * dialog.
  */</span>
  <span class='keyword'>private</span> Stock fNewStock;
  
  <span class='keyword'>private</span> JTextField fNameField;
  <span class='keyword'>private</span> JTextField fTickerField;
  <span class='keyword'>private</span> JComboBox fExchangeField;
  <span class='keyword'>private</span> JTextField fQuantityField;
  <span class='keyword'>private</span> JTextField fAveragePriceField;
  
  <span class='keyword'>private</span> JFrame fFrame;

  <span class='keyword'>private</span> <span class='keyword'>void</span> showDialog(String aTitle, Stock aInitialValue){
    Editor editor = <span class='keyword'>new</span> Editor(aTitle, fFrame, aInitialValue);
    editor.showDialog();
  }

  <span class='keyword'>private</span> <span class='keyword'>final</span> <span class='keyword'>class</span> Editor <span class='keyword'>extends</span> StandardEditor { 
    <span class='comment'>/**
    * @param aInitialValue is possibly-null; if null, then the editor represents 
    * and Add action, otherwise it represents a Change action, and all fields will
    * be pre-populated with values taken from aInitialValue.
    */</span>
    Editor(String aTitle, JFrame aParent, Stock aInitialValue){
      <span class='keyword'>super</span>(aTitle, aParent, StandardEditor.CloseAction.HIDE);
      fInitialValue = aInitialValue;
    }
    <span class='keyword'>protected</span> JComponent getEditorUI () {
      <span class='keyword'>return</span> getEditor(fInitialValue);
    }
    <span class='keyword'>protected</span> <span class='keyword'>void</span> okAction() {
      initNewStock(<span class='keyword'>this</span>);
    }
    <span class='keyword'>private</span> Stock fInitialValue;
  }  
  
  <span class='keyword'>private</span> JComponent getEditor(Stock aInitialValue){
    JPanel content = <span class='keyword'>new</span> JPanel();
    content.setLayout(<span class='keyword'>new</span> GridBagLayout());
    addCompanyName(content, aInitialValue);
    addTickerField(content, aInitialValue);
    addExchange(content, aInitialValue);
    addQuantity(content, aInitialValue);
    addAveragePrice(content, aInitialValue);
    <span class='keyword'>return</span> content;
  }

  <span class='comment'>/**
  * Set fNewStock, if the input is valid.
  *
  * If there is at least one error message in the text input fields, then
  * inform the user that the error must be corrected before proceeding.
  *
  * &lt;p&gt;If no error messages, but input still detected as faulty as 
  * per {@link Stock#isValidInput(List, String, String, Exchange, Integer, BigDecimal)}, 
  * then inform user of the problem.
  *
  * @param aEditor is the dialog which will be closed if no errors occur.
  */</span>
  <span class='keyword'>private</span> <span class='keyword'>void</span> initNewStock(StandardEditor aEditor){
    <span class='keyword'>if</span> ( hasErrorMessage() ) {
      String message = <span class='literal'>"Please correct the input error before proceeding."</span>;
      JOptionPane.showMessageDialog(
        fFrame, message, <span class='literal'>"Invalid Input"</span>, JOptionPane.INFORMATION_MESSAGE
      );
      <span class='keyword'>return</span>;
    }
    
    String name = fNameField.getText();
    String ticker = fTickerField.getText();
    Exchange exchange = Exchange.valueFrom( fExchangeField.getSelectedItem().toString() );
    Integer numShares = <span class='keyword'>null</span>;
    <span class='keyword'>if</span> ( Util.textHasContent(fQuantityField.getText()) ) {
      numShares = Integer.valueOf( fQuantityField.getText() );
    }
    <span class='keyword'>else</span> {
      numShares = Consts.ZERO;
    }
    BigDecimal avgPrice = <span class='keyword'>null</span>;
    <span class='keyword'>if</span> ( Util.textHasContent(fAveragePriceField.getText()) ) {
      avgPrice = <span class='keyword'>new</span> BigDecimal( fAveragePriceField.getText() );
    }
    <span class='keyword'>else</span> {
      avgPrice = <span class='keyword'>new</span> BigDecimal( <span class='literal'>"0.00"</span> );
    }
    
    java.util.List&lt;String&gt; errorMessages = <span class='keyword'>new</span> ArrayList&lt;String&gt;();
    <span class='keyword'>if</span> ( Stock.isValidInput( errorMessages, name, ticker, exchange, numShares, avgPrice) ) {
      fNewStock = <span class='keyword'>new</span> Stock(name, ticker, exchange, numShares, avgPrice); 
      aEditor.dispose();
    }
    <span class='keyword'>else</span> {
      Object[] message = errorMessages.toArray();
      JOptionPane.showMessageDialog(
        fFrame, message, <span class='literal'>"Invalid Input"</span>, JOptionPane.INFORMATION_MESSAGE
      );
    }
  }
  
  <span class='comment'>/**
  * Return true only if at least one of the text input fields contains 
  * an error message.
  */</span>
  <span class='keyword'>private</span> <span class='keyword'>boolean</span> hasErrorMessage(){
    <span class='keyword'>return</span> 
      fNameField.getText().startsWith(RegexInputVerifier.ERROR_MESSAGE_START) ||
      fTickerField.getText().startsWith(RegexInputVerifier.ERROR_MESSAGE_START) ||
      fQuantityField.getText().startsWith(RegexInputVerifier.ERROR_MESSAGE_START) ||
      fAveragePriceField.getText().startsWith(RegexInputVerifier.ERROR_MESSAGE_START
    );
  }

  <span class='keyword'>private</span> <span class='keyword'>void</span> addCompanyName(JPanel aContent, Stock aInitialValue) {
    fNameField = UiUtil.addSimpleEntryField(
      aContent, 
      <span class='literal'>"Company Name:"</span>, 
      (aInitialValue == <span class='keyword'>null</span> ? <span class='keyword'>null</span> : aInitialValue.getName()), 
      KeyEvent.VK_C, 
      UiUtil.getConstraints(<span class='literal'>0</span>,<span class='literal'>0</span>),
      <span class='literal'>"No spaces on the ends, and at least one character"</span>
    );
    fNameField.setInputVerifier(RegexInputVerifier.TEXT);
  }
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> addTickerField(JPanel aContent, Stock aInitialValue) {
    fTickerField = UiUtil.addSimpleEntryField(
      aContent, 
      <span class='literal'>"Ticker:"</span>, 
      (aInitialValue == <span class='keyword'>null</span> ? <span class='keyword'>null</span> : aInitialValue.getTicker()), 
      KeyEvent.VK_T, 
      UiUtil.getConstraints(<span class='literal'>1</span>,<span class='literal'>0</span>),
      <span class='literal'>"No spaces on the ends, 1-20 characters: "</span> + 
      <span class='literal'>"letters, periods, underscore and ^"</span>
    );
    String regex = <span class='literal'>"(&#092;&#092;^)?([A-Za-z._]){1,20}"</span>;
    RegexInputVerifier tickerVerifier = 
      <span class='keyword'>new</span> RegexInputVerifier(Pattern.compile(regex), RegexInputVerifier.UseToolTip.FALSE
    );
    fTickerField.setInputVerifier( tickerVerifier );
  }

  <span class='keyword'>private</span> <span class='keyword'>void</span> addExchange(JPanel aContent, Stock aInitialValue) {
    JLabel exchange = <span class='keyword'>new</span> JLabel(<span class='literal'>"Exchange:"</span>);
    exchange.setDisplayedMnemonic(KeyEvent.VK_X);
    aContent.add( exchange, UiUtil.getConstraints(<span class='literal'>2</span>,<span class='literal'>0</span>) );
    DefaultComboBoxModel exchangesModel= <span class='keyword'>new</span> DefaultComboBoxModel(Exchange.VALUES.toArray());
    fExchangeField = <span class='keyword'>new</span> JComboBox(exchangesModel);
    <span class='keyword'>if</span> (aInitialValue != <span class='keyword'>null</span>) {
      fExchangeField.setSelectedItem( aInitialValue.getExchange() );
    }
    exchange.setLabelFor(fExchangeField);
    GridBagConstraints constraints = UiUtil.getConstraints(<span class='literal'>2</span>,<span class='literal'>1</span>);
    constraints.fill = GridBagConstraints.HORIZONTAL;
    aContent.add(fExchangeField, constraints);
  }
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> addQuantity(JPanel aContent, Stock aInitialValue) {
    fQuantityField = UiUtil.addSimpleEntryField(
      aContent, 
      <span class='literal'>"Quantity:"</span>, 
      (aInitialValue == <span class='keyword'>null</span> ? <span class='keyword'>null</span> : 
      aInitialValue.getNumShares().toString()), 
      KeyEvent.VK_Q, 
      UiUtil.getConstraints(<span class='literal'>3</span>,<span class='literal'>0</span>),
      <span class='literal'>"Zero or Integer (possible leading minus sign)"</span>
    );
    fQuantityField.setInputVerifier(RegexInputVerifier.INTEGER);
  }
  
  <span class='keyword'>private</span> <span class='keyword'>void</span> addAveragePrice(JPanel aContent, Stock aInitialValue) {
    fAveragePriceField = UiUtil.addSimpleEntryField(
      aContent, 
       <span class='literal'>"Average Price:"</span>, 
      (aInitialValue == <span class='keyword'>null</span> ? <span class='keyword'>null</span> : 
      aInitialValue.getAveragePrice().toString()), 
      KeyEvent.VK_A, 
      UiUtil.getConstraints(<span class='literal'>4</span>,<span class='literal'>0</span>),
      <span class='literal'>"Zero or Positive Number (two decimals optional)"</span>
    );
    fAveragePriceField.setInputVerifier(RegexInputVerifier.NON_NEGATIVE_MONEY);
  }
}
 
</PRE>
<br>
<br>
<br>

</div>




<div class='topic-section'>See Also :</div>
<div class='main-body'>
 
  
  <a href='TopicAction7910-2.html?Id=150'>Standardized dialogs</a> <br>
 
  
  <a href='TopicActioncded-2.html?Id=151'>Verify input with regular expressions</a> <br>
 
  
  <a href='TopicActiond281-2.html?Id=233'>Verify input with Model Objects</a> <br>
 
</div>


<div class='topic-section'>Would you use this technique?</div>
<div class='main-body'>
  
  <form action="http://www.javapractices.com/vote/AddVoteAction.do" method='post'>
    Yes<input type='radio' name='Choice' value='Y' >
    &nbsp;&nbsp;No<input type='radio' name='Choice' value='N'>
    &nbsp;&nbsp;Undecided<input type='radio' name='Choice' value="?" >
    &nbsp;&nbsp;<input type=submit value="Vote" >
    <input type='hidden' name='Operation' value='Apply'>
    <input type='hidden' name='TopicId' value='167'>
  </form>
</div>

<div style='height:10.0em;'></div>

 
 
</div>

  

 





<div align='center' class='legalese'>  
&copy; 2011 Hirondelle Systems |
<a href='../source/SourceAction-2.html'><b>Source Code</b></a><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |
<a href="mailto:webmaster@javapractices.com">Contact</a> |
<a href="http://creativecommons.org/licenses/by-nc-sa/1.0/">License</a> |
<a href='../apps/cjp.rss'>RSS</a>
<!-- ukey="2AC36CD2" -->
<!-- ckey="16DF3D87" -->
<br>

 Individual code snippets can be used under this <a href='../LICENSE.txt'>BSD license</a> - Last updated on June 6, 2010.<br>
 Over 150,000 unique IPs last month - <span title='Java Practices 2.6.5, Mon May 16 00:00:00 EDT 2011'>Built with</span> <a href='http://www.web4j.com/'>WEB4J</a>.<br>
 - In Memoriam : Bill Dirani -
</div>

<script src="../../www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2633428-1";
urchinTracker();
</script>



</body>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do?Id=167 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:28:07 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
</html>
